package com.tarena.lbs.basic.web.filters;

import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.basic.web.utils.UserPrincipleThreadLocal;
import com.tarena.lbs.common.passport.encoder.JwtEncoder;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

//@Component
@Slf4j
public class MyFilter01 implements Filter {
    private static final String HEADER_AUTH="Authorization";
    //@Autowired
    private JwtEncoder<UserPrinciple> jwtEncoder;
    /**
     * 过滤器核心方法doFilter
     * @param servletRequest 请求对象 封装的是servlet请求 但是web应用一定是httpServletRequest
     * @param servletResponse 响应对象 封装的是servlet响应 但是web应用一定是httpServletResponse
     * @param filterChain 过滤器链 连接过滤器到web容器 下一个流程的关键对象
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //请求进入的逻辑
        //先准备好 存放在线程上游的认证对象
        UserPrinciple userPrinciple = null;
        log.info("请求进入经过过滤器");
        //1.判断是否是http请求
        if (servletRequest instanceof HttpServletRequest) {
            //转化
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            //2.获取头 Authorization
            String jwt = request.getHeader(HEADER_AUTH);
            //判断空 "" null
            if (StringUtils.isNotBlank(jwt)) {
                //3.try catch解析
                try {
                    userPrinciple = jwtEncoder.getLoginFromToken(jwt, UserPrinciple.class);
                    log.info("解析jwt成功,拿到认证user:{}", userPrinciple);
                    //认证解析成功 想办法将userPrinciple传递给后端业务代码
                    UserPrincipleThreadLocal.save(userPrinciple);
                    log.info("过滤器向ThreadLocal存储解析对象");
                } catch (BusinessException e) {
                    //只打印日志
                    log.error("过滤器解析jwt失败", e);
                }
            }
        }
        //必须按照要求 调用下一个组件 只有经过filterChain向后调用的doFilter方法 请求才能到达controller
        filterChain.doFilter(servletRequest,servletResponse);
        //请求结束 响应返回的逻辑
        log.info("响应返回经过过滤器");
        //当响应结束的时候 释放一下当前线程存储的数据,如果不清除数据 会导致高并发时线程复用 数据错乱
        UserPrincipleThreadLocal.clear();
    }
}
